package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.settlement.bo.ExportBO;
import com.tiancheng.trade.settlement.bo.MerchantQueryBo;
import com.tiancheng.trade.settlement.enums.CheckDetailDifferentTypeEnum;
import com.tiancheng.trade.settlement.enums.OrderSourceEnum;
import com.tiancheng.trade.settlement.enums.SettleSummaryDataStatus;
import com.tiancheng.trade.settlement.enums.SettlementTypeEnum;
import com.tiancheng.trade.settlement.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.settlement.mapper.merchant.MerchantMapper;
import com.tiancheng.trade.settlement.mapper.settlement.SettleSummaryMapper;
import com.tiancheng.trade.settlement.model.settlement.SettleSummary;
import com.tiancheng.trade.settlement.service.settlement.ISettleDetailService;
import com.tiancheng.trade.settlement.service.settlement.ISettleSummaryService;
import com.tiancheng.trade.settlement.util.ExcelUtil;
import com.tiancheng.trade.settlement.vo.settlement.admin.SettleDetailQueryVo;
import com.tiancheng.trade.settlement.vo.settlement.admin.SettleQueryVo;
import com.tiancheng.trade.settlement.vo.settlement.admin.res.SettleDetailResVo;
import com.tiancheng.trade.settlement.vo.settlement.export.SettleByMerchantDetailExportVo;
import com.tiancheng.trade.settlement.vo.settlement.export.SettleByMerchantExportVo;
import com.tiancheng.trade.settlement.vo.settlement.export.SettleExportAllQueryVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * * 交易资金对账汇总表service
 *
 * @author likailun
 * @date 2021/3/30
 */
@Service
@Slf4j
public class SettleSummaryServiceImpl extends ServiceImpl<SettleSummaryMapper, SettleSummary> implements ISettleSummaryService {

    @Autowired
    private SettleSummaryMapper settleSummaryMapper;
    @Autowired
    private ISettleDetailService settleDetailService;
    @Autowired
    private MerchantMapper merchantMapper;

    @Override
    public SettleSummary querySettleSummaryOne(SettleQueryVo queryParams) {
        QueryWrapper<SettleSummary> conditions = new QueryWrapper<>();
        conditions.eq("actual_clear_date", queryParams.getActualClearDate());
        conditions.in("data_status", Arrays.asList(SettleSummaryDataStatus.EFFECTIVE.getCode(), SettleSummaryDataStatus.PARTIALLY_EFFECTIVE.getCode()));
        conditions.eq("merchant_code", queryParams.getMerchantCode());
        conditions.eq("pay_channel", queryParams.getPayChannel());
        SettleSummary settleSummary = settleSummaryMapper.selectOne(conditions);
        BusinessErrorInfoEnum.QUERY_NOT_EXIST_SETTLESUMMARY_ERROR.assertNotNull(settleSummary);
        return settleSummary;
    }

    @Override
    public void exportByMerchant(SettleQueryVo settleQueryVo, HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            SettleSummary settleSummary = this.querySettleSummaryOne(settleQueryVo);
            // 商户汇总
            SettleByMerchantExportVo settleByMerchantExportVo = SettleByMerchantExportVo.build(settleSummary);
            // 商户对账明细,最多查询5w条
            SettleDetailQueryVo settleDetailQueryVo = new SettleDetailQueryVo();
            settleDetailQueryVo.setCheckCode(settleSummary.getCheckCode());
            settleDetailQueryVo.setCurrentPage(1);
            settleDetailQueryVo.setPageSize(50000);
            Set<Integer> set = new HashSet<>();
            set.add(CheckDetailDifferentTypeEnum.MD_OWN.getCode());
            set.add(CheckDetailDifferentTypeEnum.MD_NON.getCode());
            set.add(CheckDetailDifferentTypeEnum.DOUBLE.getCode());
            settleDetailQueryVo.setDifferentTypes(set);
            PageInfo<SettleDetailResVo> pageInfo = settleDetailService.findList(settleDetailQueryVo);
            List<SettleByMerchantDetailExportVo> details = new ArrayList<>();
            for (SettleDetailResVo detailResVo : pageInfo.getList()) {
                details.add(SettleByMerchantDetailExportVo.build(detailResVo));
            }

            String fileName = String.format("%s%s对账.xlsx", settleSummary.getMerchantName(), DateTimeUtil.format(settleSummary.getActualClearDate(), DateTimeUtil.yyyyMMdd));
            List<ExportBO> exportBOS = new ArrayList<>();
            String[] allTitleSummary = {"应清算日期", "交易渠道", "机构名称", "商户名称", "清分类型", "业务场景", "平台", "渠道", "差异", "平台", "渠道", "差异", "平台", "渠道", "差异", "平台抽佣", "对账状态"};
            TreeMap<Integer, String> mergeTitleSummary = new TreeMap<>();
            mergeTitleSummary.put(0, "基础数据");
            mergeTitleSummary.put(6, "交易金额");
            mergeTitleSummary.put(9, "退款金额");
            mergeTitleSummary.put(12, "净额");

            Map<String, MerchantQueryBo> oMap = merchantMapper.findByMerchantCods(Collections.singletonList(settleSummary.getMerchantCode()))
                    .stream().collect(Collectors.toMap(MerchantQueryBo::getMerchantCode, Function.identity(), (oldValue, newValue) -> newValue));
            settleByMerchantExportVo.setOrganizationName(oMap.get(settleSummary.getMerchantCode()) == null ? "" : oMap.get(settleSummary.getMerchantCode()).getOrganizationName());
            settleByMerchantExportVo.setSettleRuleName(oMap.get(settleSummary.getMerchantCode()) == null ? "" : SettlementTypeEnum.getDesc(oMap.get(settleSummary.getMerchantCode()).getSettlementType()));
            settleByMerchantExportVo.setSourcesName(oMap.get(settleSummary.getMerchantCode()) == null ? "" : OrderSourceEnum.getSourcesNames(oMap.get(settleSummary.getMerchantCode()).getScene()));
            ExportBO exportBOSummary = new ExportBO("对账汇总", mergeTitleSummary, allTitleSummary, Collections.singletonList(settleByMerchantExportVo));
            exportBOS.add(exportBOSummary);

            // 明细数据
            String[] allTitleDetail = {"交易时间", "子订单号", "渠道支付单号", "商户名称", "应收金额", "实收金额", "优惠金额", "退款金额", "清出金额", "订单状态", "核销时间", "差异备注", "清分规则"};
            ExportBO exportBODetail = new ExportBO("对账明细", null, allTitleDetail, details);
            exportBOS.add(exportBODetail);
            Workbook workbook = ExcelUtil.buildExcelWorkBook(exportBOS);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        } catch (Exception e) {
            log.error("导出失败:{}", e.getMessage());
            throw new Exception("导出失败", e);
        }
    }

    @Override
    public void exportAll(SettleExportAllQueryVo queryVo, HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 最多查询一个月的数据
        try {
            BusinessErrorInfoEnum.QUERY_ARGS_ERROR.assertIsTrue(queryVo.getStartDate().equals(queryVo.getEndDate()) || (queryVo.getStartDate().isBefore(queryVo.getEndDate()) &&
                    queryVo.getEndDate().toEpochDay() - queryVo.getStartDate().toEpochDay() <= 31));
            QueryWrapper<SettleSummary> conditions = new QueryWrapper<>();
            conditions.ge("actual_clear_date", queryVo.getStartDate());
            conditions.le("actual_clear_date", queryVo.getEndDate());
            conditions.eq("data_status", SettleSummaryDataStatus.EFFECTIVE.getCode());
            List<SettleSummary> settleSummaries = settleSummaryMapper.selectList(conditions);
            BusinessErrorInfoEnum.QUERY_NOT_EXIST_SETTLESUMMARY_ERROR.assertIsTrue(!CollectionUtils.isEmpty(settleSummaries));

            String fileName = String.format("%s到%s对账汇总.xlsx", DateTimeUtil.format(queryVo.getStartDate(), DateTimeUtil.yyyyMMdd), DateTimeUtil.format(queryVo.getEndDate(), DateTimeUtil.yyyyMMdd));
            List<ExportBO> exportBOS = new ArrayList<>();
            String[] allTitleSummary = {"应清算日期", "交易渠道", "机构名称", "商户名称", "结算类型", "业务场景", "平台", "渠道", "差异", "平台", "渠道", "差异", "平台", "渠道", "差异", "平台抽佣", "对账状态"};
            TreeMap<Integer, String> mergeTitleSummary = new TreeMap<>();
            mergeTitleSummary.put(0, "基础数据");
            mergeTitleSummary.put(6, "交易金额");
            mergeTitleSummary.put(9, "退款金额");
            mergeTitleSummary.put(12, "净额");

            Set<String> merchantCodes = settleSummaries.stream().map(SettleSummary::getMerchantCode).collect(Collectors.toSet());

            Map<String, MerchantQueryBo> oMap = merchantMapper.findByMerchantCods(merchantCodes)
                    .stream().collect(Collectors.toMap(MerchantQueryBo::getMerchantCode, Function.identity(), (oldValue, newValue) -> newValue));

            List<SettleByMerchantExportVo> settleByMerchantExportVos = new ArrayList<>();
            for (SettleSummary settleSummary : settleSummaries) {
                SettleByMerchantExportVo settleByMerchantExportVo = SettleByMerchantExportVo.build(settleSummary);
                settleByMerchantExportVo.setOrganizationName(oMap.get(settleSummary.getMerchantCode()) == null ? "" : oMap.get(settleSummary.getMerchantCode()).getOrganizationName());
                settleByMerchantExportVo.setSourcesName(oMap.get(settleSummary.getMerchantCode()) == null ? "" : OrderSourceEnum.getSourcesNames(oMap.get(settleSummary.getMerchantCode()).getScene()));
                settleByMerchantExportVo.setSettleRuleName(oMap.get(settleSummary.getMerchantCode()) == null ? "" : SettlementTypeEnum.getDesc(oMap.get(settleSummary.getMerchantCode()).getSettlementType()));
                settleByMerchantExportVos.add(settleByMerchantExportVo);
            }

            ExportBO exportBOSummary = new ExportBO(fileName.replace(".xlsx", ""), mergeTitleSummary, allTitleSummary, settleByMerchantExportVos);
            exportBOS.add(exportBOSummary);
            Workbook workbook = ExcelUtil.buildExcelWorkBook(exportBOS);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        } catch (Exception e) {
            log.error("批量导出对账汇总异常:{}", e.getMessage());
            throw new Exception("导出失败", e);
        }
    }

    @Override
    public void updateBatch(List<String> checkCodes, Integer dataStatus) {
        settleSummaryMapper.updateBatch(checkCodes, dataStatus);
    }

    /**
     * 对账结果列表获取
     *
     * @param settleQueryVo
     * @return
     */
    @Override
    public PageInfo<SettleSummary> listSettleSummary(SettleQueryVo settleQueryVo) {
        PageInfo<SettleSummary> pageInfo = new PageInfo<>();
        long count = settleSummaryMapper.selectCount(new QueryWrapper<SettleSummary>() {{
            if (settleQueryVo.getActualClearDate() != null) {
                eq("actual_clear_date", settleQueryVo.getActualClearDate());
            }
            in("data_status", Arrays.asList(SettleSummaryDataStatus.EFFECTIVE.getCode(), SettleSummaryDataStatus.PARTIALLY_EFFECTIVE.getCode()));
            if (!StringUtils.isEmpty(settleQueryVo.getPayChannel())) {
                eq("pay_channel", settleQueryVo.getPayChannel());
            }
            if (!StringUtils.isEmpty(settleQueryVo.getMerchantCode())) {
                eq("merchant_code", settleQueryVo.getMerchantCode());
            }
        }});
        if (count > 0) {
            List<SettleSummary> list = settleSummaryMapper.listSettleSummary(settleQueryVo);
            pageInfo.setList(list);
            pageInfo.setPagination(new PageInfo.Pagination() {{
                setPageSize(settleQueryVo.getPageSize());
                setCurrentPage(settleQueryVo.getCurrentPage());
                setTotal(count);
            }});
        }
        return pageInfo;
    }

}
